home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i053: News/mail gateway package, Part03/04
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 6342786c 23d62120 ba41572d 33d067e2
-
- Submitted-by: Rich $alz <rsalz@bbn.com>
- Posting-number: Volume 24, Issue 53
- Archive-name: newsgate/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: gate.h hdr.c lex.l mail-interface mail2news.1 misc.c
- # news2mail.1 signoff.c sysexits.h uucp-2-inet
- # Wrapped by rsalz@litchi.bbn.com on Fri Mar 15 16:42:27 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 3 (of 4)."'
- if test -f 'gate.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'gate.h'\"
- else
- echo shar: Extracting \"'gate.h'\" \(6518 characters\)
- sed "s/^X//" >'gate.h' <<'END_OF_FILE'
- X/*
- X** HEADER FILE FOR NEWS/MAIL GATEWAY CODE.
- X** $Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/gate.h,v 1.12 91/03/13 15:59:23 rsalz Exp $
- X*/
- X
- X
- X/*
- X** START OF CONFIGURATION SECTION
- X*/
- X
- X
- X/* Paths to some parts of your netnews installation. Required. */
- X#define INEWS "/usr/lib/news/inews"
- X#define ACTIVE "/usr/lib/news/active"
- X#define NGDELIM ','
- X
- X
- X/* In writing Paths into From addresses, we can look at the output
- X * of uuname from the L.sys file. Define both or neither of the next
- X * two. We can also map some UUCP names to their domain names, if
- X * the third line is enabled. The UUCP_INET should match the value
- X * in the Makefile. This violates the "write once" rule, but it's
- X * too much of a pain to fix for this one symbol. */
- X#define UUNAME "/usr/lib/news/.admin/uuname.out"
- X#define L_SYS "/usr/lib/uucp/L.sys"
- X#define UUCP_INET "/usr/lib/news/.admin/uucp-2-inet"
- X
- X
- X/* Where does the control file for talk.foo live?
- X * IN_ONEPLACE: specified filename
- X * IN_SPOOLDIR: /usr/spool/news/talk/foo/recnews.cmd
- X * IN_CMDDIR: /usr/lib/news/.admin/talk.foo
- X * One of these is required, but you can set IN_ONEPLACE to /dev/null to
- X * disable the newsgroup editing. */
- X/*efine IN_ONEPLACE "/dev/null" /* .. */
- X/*efine IN_SPOOLDIR "/usr/spool/news" /* .. */
- X#define IN_CMDDIR "/usr/lib/news/.admin" /* .. */
- X
- X
- X/* What do you want to do with the Path: line? Put in a fixed string
- X * (such as pointing to a mail reflector saying "Don't trust Path:
- X * lines as a way to reply"). Put a fixed "fake host" in the Path:,
- X * or just put the user's host there. The latter two can cause the
- X * poster's site to never get the article. Anyhow, pick one. To pick
- X * neither #define is to get the third behavior -- the user's host. */
- X#define FIXED_PATH "news-mail-gateway" /* .. */
- X/*efine GATEWAY_NAME "gateway" /* .. */
- X
- X
- X/* The code in hdr.c does lots of work to canonicalize addresses. You
- X * shouldn't disable it, but at least one beta-tester wanted to, sigh. */
- X#define DO_ADDRESS_CLEANUP /* .. */
- X
- X
- X/* Are you running sendmail or MMDF? Pick one. If you believe in
- X * trusted users (MMDF doesn't?) to lie to your mailer, set the
- X * user-ID. */
- X/*efine SENDMAIL "/usr/lib/sendmail" /* .. */
- X#define MMDF "/usr/mmdf/lib/submit" /* .. */
- X/*efine TRUSTED 1 /* .. */
- X
- X
- X/* Does your Sendmail mailer have the M flag on? */
- X#ifdef SENDMAIL
- X#define REQUIRE_MESSAGE_ID /* .. */
- X#endif /* SENDMAIL */
- X
- X
- X/* I love how we all speak the same language. */
- X/*efine CATCHER int /* Type of a signal-catcher */
- X#define CATCHER void /* .. */
- X#define IDX index /* .. */
- X#define RDX rindex /* .. */
- X/*efine IDX strchr /* .. */
- X/*efine RDX strrchr /* .. */
- Xtypedef int *align_t; /* Worst-case alignment, for lint */
- X#define CHARSTAR_SPRINTF /* Need extern char *sprintf(); */
- X#define VOID_EXIT /* Need extern void exit(); */
- X#define HAVE_SYSEXITS /* Have <sysexits.h>? */
- X#define HAVE_TIMEB /* Have <sys/timeb.h>? */
- X#define HAVE_PUTENV /* Have putenv(3) */
- X/*efine HAVE_STRERROR /* Have strerror(3)? */
- X
- X#define SM_SIZE 512 /* A smallish buffer size */
- X#define LG_SIZE 1024 /* big buffer size */
- X
- X/* Error log (stderr) for news2mail. */
- X#define ERR_LOG "/usr/lib/news/.admin/news2mail.out"
- X#define TEMPFILE "/tmp/gateXXXXXX" /* Temporary file pattern */
- X
- X
- X/* Enable debugging code? */
- X#define STATIC static
- X#ifdef lint
- X#undef RCSID
- X#else
- X#define RCSID
- X#endif /* lint */
- X
- X/*
- X** END OF CONFIGURATION SECTION.
- X*/
- X
- X
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X
- X#ifdef HAVE_SYSEXITS
- X#include <sysexits.h>
- X#else
- X#include "sysexits.h"
- X#endif /* HAVE_SYSEXITS */
- X
- X
- Xtypedef struct _HBUF {
- X char approved[SM_SIZE]; /* Approved: */
- X char ctlmsg[LG_SIZE]; /* Control: */
- X char subdate[SM_SIZE]; /* Date: (submission) */
- X char distribution[SM_SIZE]; /* Distribution: */
- X char expdate[SM_SIZE]; /* Expires: */
- X char followto[SM_SIZE]; /* Followup-to: */
- X char from[SM_SIZE]; /* From: */
- X char followid[SM_SIZE]; /* References: */
- X char keywords[SM_SIZE]; /* Keywords: */
- X char ident[SM_SIZE]; /* Message-ID: */
- X char nbuf[LG_SIZE]; /* Newsgroups: */
- X char organization[SM_SIZE]; /* Organization: */
- X char title[SM_SIZE]; /* Subject: */
- X char replyto[SM_SIZE]; /* Reply-To: */
- X char summary[SM_SIZE]; /* Summary: */
- X char path[LG_SIZE]; /* Path: */
- X char sender[SM_SIZE]; /* Sender: */
- X} HBUF;
- X
- X
- X/* String and memory manipulators. */
- X#define APPEND(p, t) strlen(strcpy((p), (t)))
- X#define NEW(T, c) (T *)MyAlloc((c) * sizeof (T))
- X#define COPY(s) ((s) ? strcpy(NEW(char, strlen((s)) + 1), (s)) : NULL)
- X#define REALLOC(p, s) realloc((char *)(p), (unsigned int)(s))
- X
- X
- X/* Array sizing. */
- X#define SIZEOF(x) (sizeof x / sizeof x[0])
- X#define ENDOF(x) (&x[SIZEOF(x)])
- X
- X
- X/* String and character operations. */
- X#define WHITE(c) ((c) == ' ' || (c) == '\t')
- X#define EQ(a, b) ((a)[0] == (b)[0] && strcmp((a), (b)) == 0)
- X#define EQn(a, b, n) ((a)[0] == (b)[0] && strncmp((a), (b), (n)) == 0)
- X#define NETCHR(c) ((c) == '.' || (c) == '%' || (c) == '@' || (c) == '!')
- X#define CHREQ(c, d) ((d) == (islower((c)) ? toupper((c)) : (c)))
- X
- X
- X/* Fundamental constants of the universe. */
- X#define TRUE 1
- X#define FALSE 0
- X#define FAIL (-1)
- X
- X
- X/* SHUT UP! */
- X#ifdef lint
- X#undef putc
- X#undef putchar
- X#endif /* lint */
- X
- X#define Close (void)close
- X#define Fflush (void)fflush
- X#define Fprintf (void)fprintf
- X#define Fputs (void)fputs
- X#define Signal (void)signal
- X#define Sprintf (void)sprintf
- X#define Strcpy (void)strcpy
- X#define Strcat (void)strcat
- X#define Strncpy (void)strncpy
- X
- X
- X/*
- X** External declarations.
- X*/
- X
- X/* Program name; exists once for each main(). */
- Xextern char *Pname;
- X
- X/* Routines we provide. */
- Xextern align_t MyAlloc();
- Xextern int Split();
- Xextern int CrackFrom();
- Xextern void re_modw();
- Xextern void SplitFree();
- Xextern void FreeFile();
- Xextern char **ReadFile();
- Xextern char *re_comp();
- Xextern char *HackHeader();
- X
- Xextern char *strerror();
- X
- X/* Variables and routines that Unix(tm) provides. */
- Xextern int errno;
- Xextern int sys_nerr;
- Xextern int optind;
- Xextern char *sys_errlist[];
- Xextern char **environ;
- Xextern char *optarg;
- X
- Xextern FILE *popen();
- Xextern char *IDX();
- Xextern char *RDX();
- Xextern char *ctime();
- Xextern char *malloc();
- Xextern char *mktemp();
- Xextern char *realloc();
- Xextern char *strcat();
- Xextern char *strncat();
- Xextern char *strcpy();
- Xextern char *strncpy();
- X#ifdef CHARSTAR_SPRINTF
- Xextern char *sprintf();
- X#endif /* CHARSTAR_SPRINTF */
- X#ifdef VOID_EXIT
- Xextern void exit();
- X#endif /* VOID_EXIT */
- END_OF_FILE
- if test 6518 -ne `wc -c <'gate.h'`; then
- echo shar: \"'gate.h'\" unpacked with wrong size!
- fi
- # end of 'gate.h'
- fi
- if test -f 'hdr.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hdr.c'\"
- else
- echo shar: Extracting \"'hdr.c'\" \(10652 characters\)
- sed "s/^X//" >'hdr.c' <<'END_OF_FILE'
- X/*
- X** Header-cracking and address re-writing routines, with sincere
- X** apologies to Upas and Sendmail.
- X*/
- X#include "gate.h"
- X#include <netdb.h>
- X#ifdef RCSID
- Xstatic char RCS[] =
- X "$Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/hdr.c,v 1.15 91/03/15 16:39:42 rsalz Exp $";
- X#endif /* RCSID */
- X
- X
- X#ifdef TEST
- X#ifndef DO_FIX_ADDRESS
- X#define DO_FIX_ADDRESS
- X#endif /* DO_FIX_ADDRESS */
- X#define dprintf(string, buff) (void)printf((string), (buff))
- X#else
- X#define dprintf(string, buff) /* NULL */
- X#endif /* TEST */
- X
- X
- X/*
- X** List of domains that we recognize.
- X*/
- XSTATIC char RELAY_CS_NET[] = "RELAY.CS.NET";
- XSTATIC char *Domains[] = {
- X /* Don't undo the % hack for sites @RELAY.CS.NET, sigh #1. */
- X RELAY_CS_NET,
- X /* These aren't official domains, but we use them, sigh #2. */
- X ".BITNET",
- X ".UUCP",
- X /* Official organizational domains. */
- X ".ARPA", ".COM", ".EDU", ".GOV", ".INT", ".MIL",
- X ".NATO", ".NET", ".ORG",
- X /* Official natonal domans. */
- X ".AR", ".AT", ".AU", ".BE", ".BR", ".CA", ".CH", ".CL",
- X ".CN", ".CR", ".CS", ".DE", ".DK", ".EC", ".EG", ".ES",
- X ".FI", ".FR", ".GR", ".HK", ".HU", ".IE", ".IL", ".IN",
- X ".IS", ".IT", ".JP", ".KR", ".LK", ".MX", ".MY", ".NI",
- X ".NL", ".NO", ".NZ", ".PH", ".PL", ".PR", ".PT", ".SE",
- X ".SG", ".SU", ".TH", ".TR", ".TW", ".UK", ".US", ".UY",
- X ".YU", ".ZA"
- X};
- X
- X
- X/*
- X** Local user?
- X*/
- XSTATIC int
- XLocal(p)
- X register char *p;
- X{
- X for ( ; *p; p++)
- X if (NETCHR(*p))
- X break;
- X return *p == '\0';
- X}
- X
- X
- X/*
- X** Case-insensitive strncmp.
- X*/
- XSTATIC char *
- XFound(dp, p)
- X register char *dp;
- X register char *p;
- X{
- X register char *q;
- X register char *r;
- X
- X for ( ; *p; p++)
- X if (CHREQ(*p, *dp)) {
- X for (q = p, r = dp; *r && CHREQ(*q, *r); q++, r++)
- X ;
- X if (*r == '\0')
- X return p;
- X }
- X
- X return NULL;
- X}
- X
- X
- X/*
- X** Find all domain names and make them uppercase:
- X** joe%site.edu@relay.cs.net --> joe%site.EDU@RELAY.CS.NET
- X*/
- XSTATIC void
- XCasify(p)
- X register char *p;
- X{
- X register char *q;
- X register char *r;
- X register char **dp;
- X
- X for (dp = Domains; dp < ENDOF(Domains); dp++)
- X for (q = p; q = Found(*dp, q); )
- X for (r = *dp; *r; *q++ = *r++)
- X ;
- X}
- X
- X
- X/*
- X** Handle route-addresses:
- X** @cruft:joe@site --> joe@site
- X*/
- XSTATIC void
- XRouteAddr(p)
- X register char *p;
- X{
- X register char *q;
- X register char *r;
- X
- X for (r = p; *p == '@'; p = q)
- X if ((q = IDX(p, ':')) && IDX(q, '@'))
- X *q++ = '\0';
- X else
- X break;
- X if (p > r)
- X /* Avoid overlaping strcpy() call. */
- X while (*r++ = *p++)
- X ;
- X}
- X
- X/*
- X** Does the pattern exist in the character range between p and end?
- X*/
- XSTATIC int
- XBetween(p, pat, q)
- X register char *p;
- X register char *pat;
- X register char *q;
- X{
- X register char *r;
- X
- X for (r = pat + strlen(pat); p < q && r >= pat && *--q == *--r; )
- X ;
- X return *r == '\0';
- X}
- X
- X
- X/*
- X** Handle the '%' syntax:
- X** joe%site.EDU@gateway.DOMAIN -> joe@site.EDU
- X*/
- XSTATIC void
- XPercent(p)
- X register char *p;
- X{
- X register char *q;
- X register char *r;
- X register char **dp;
- X
- X while ((r = IDX(p, '%')) && (q = IDX(r, '@'))) {
- X for (dp = Domains; dp < ENDOF(Domains); dp++) {
- X if (*dp == RELAY_CS_NET)
- X continue;
- X if (Between(r, *dp, q)) {
- X *RDX(p, '@') = '\0';
- X *RDX(p, '%') = '@';
- X break;
- X }
- X }
- X if (dp == ENDOF(Domains))
- X break;
- X }
- X}
- X
- X
- X/*
- X** Handle CSNET, which is domainist except in some people's minds:
- X** joe%site@RELAY.CS.NET --> joe@site.CSNET
- X** joe%site.EDU@RELAY.CS.NET --> joe@site.EDU
- X*/
- XSTATIC void
- XCsnet(p)
- X register char *p;
- X{
- X register char *q;
- X register char *r;
- X
- X if ((q = RDX(p, '@'))
- X && strcmp(q, "@RELAY.CS.NET") == 0
- X && (r = RDX(p, '%'))) {
- X *RDX(p, '@') = '\0';
- X *r = '@';
- X if (IDX(r, '.') == NULL)
- X Strcat(p, ".CSNET");
- X }
- X}
- X
- X
- X/*
- X** Handle hybrid "!" and "@" addresses:
- X** a!site!joe@site --> joe@site
- X** a!site!joe --> joe@site.UUCP
- X** a!site.EDU!joe --> joe@site.EDU
- X*/
- XSTATIC void
- XHybrid(p)
- X register char *p;
- X{
- X register char *q;
- X register char *user;
- X char buff[SM_SIZE];
- X
- X if (user = RDX(p, '!')) {
- X *user++ = '\0';
- X if (q = IDX(user, '@'))
- X *q = '\0';
- X q = (q = RDX(p, '!')) ? q + 1 : p;
- X Sprintf(buff, "%s@%s", user, q);
- X if (IDX(q, '.') == NULL)
- X Strcat(buff, ".UUCP");
- X Strcpy(p, buff);
- X }
- X}
- X
- X
- X/*
- X** Handle special case for Australia:
- X** user@site.OZ --> user@site.OZ.AU
- X*/
- XSTATIC void
- XEndpart(p)
- X register char *p;
- X{
- X register char *r;
- X
- X if ((r = RDX(p, '.')) && r[1] == 'O' && r[2] == 'Z' && r[3] == '\0')
- X Strcpy(&r[3], ".AU");
- X}
- X
- X
- X/*
- X** General address canonicalizer.
- X*/
- XSTATIC char *
- XFixAddress(p)
- X register char *p;
- X{
- X static char buff[1024];
- X char host[128];
- X
- X if (Local(p)) {
- X if (gethostname(host, sizeof host) < 0) {
- X Fprintf(stderr, "%s: Can't get my hostname, %s.\n",
- X Pname, strerror(errno));
- X exit(EX_TEMPFAIL);
- X }
- X Sprintf(buff, "%s@%s", p, host);
- X }
- X else {
- X Strcpy(buff, p);
- X Casify(buff);
- X dprintf(" Casify returns %s\n", buff);
- X RouteAddr(buff);
- X dprintf("RouteAddr returns %s\n", buff);
- X Percent(buff);
- X dprintf(" Percent returns %s\n", buff);
- X Csnet(buff);
- X dprintf(" Csnet returns %s\n", buff);
- X Hybrid(buff);
- X dprintf(" Hybrid returns %s\n", buff);
- X Endpart(buff);
- X dprintf(" Endpart returns %s\n", buff);
- X }
- X return buff;
- X}
- X
- X
- X/*
- X** This subroutine is a concession to the realities of the Internet and
- X** and the USENET. Much as the idea is distasteful and likely to get me
- X** in trouble, I have to hack message-ids into a format that the USENET
- X** won't choke on. Pray that if we're doing multiple insertion point
- X** gatewaying that ALL the gateways mung exactly the same things.
- X**
- X** (Death to HERMES! Death to UNIX/MM-11! Death to EAN!)
- X*/
- XSTATIC int
- XFixMessageID(s)
- X register char *s;
- X{
- X register int atdot;
- X register int closed;
- X
- X /* Quickie tests -- why waste time? */
- X if (*s != '<')
- X return FALSE;
- X
- X for (atdot = FALSE, closed = FALSE; *++s; )
- X switch (*s) {
- X default:
- X if (!isascii(*s) || iscntrl(*s) || isspace(*s))
- X return FALSE;
- X break;
- X case '<':
- X /* Already got one. */
- X return FALSE;
- X case '>':
- X /* I hope no one is stupid enough to quote this... */
- X closed = TRUE;
- X s[1] = '\0';
- X break;
- X case '.':
- X case '@':
- X /* We should check for a domain spec, not just either/or. */
- X atdot = TRUE;
- X break;
- X case '\t':
- X case ' ':
- X case '/':
- X /* Avoid various problem characters. */
- X *s = '.';
- X break;
- X }
- X
- X return atdot && closed;
- X}
- X
- X
- X/*
- X** Fix up the contents of In-Reply-To: fields and References: fields.
- X*/
- XSTATIC void
- XFixReferences(hp)
- X register HBUF *hp;
- X{
- X register char *cp;
- X register char *ep;
- X register char *p;
- X register char *max;
- X char scratch[LG_SIZE];
- X
- X cp = hp->followid;
- X max = cp + strlen(cp);
- X for (p = scratch; cp = IDX(cp, '<'); ) {
- X if ((ep = IDX(cp, '>')) == NULL
- X || ((ep - cp) + 1) > sizeof scratch - (p - scratch + 2))
- X /* Unterminated ID, or no more room. */
- X break;
- X
- X if (FixMessageID(cp)) {
- X if (p > scratch) {
- X *p++ = ' ';
- X *p++ = '\0';
- X }
- X p += APPEND(p, cp);
- X }
- X cp = ep + 2;
- X if (cp >= max)
- X break;
- X }
- X Strcpy(hp->followid, scratch);
- X}
- X
- X
- X/*
- X** Count the number of '@' in the string.
- X*/
- XSTATIC int
- XAtCount(s)
- X register char *s;
- X{
- X register int n;
- X
- X for (n = 0; *s; s++)
- X if (*s == '@')
- X n++;
- X return n;
- X}
- X
- X
- X/*
- X** Canonicalize the "From:" line into the form
- X** From: local-part@domain (full-name)
- X** RFC822 doesn't require the comment to be at the end of the string
- X** like that.
- X*/
- XSTATIC void
- XFixFrom(hp)
- X register HBUF *hp;
- X{
- X register char *p;
- X register struct hostent *host;
- X char address[LG_SIZE];
- X char fullname[LG_SIZE];
- X char scratch[sizeof address];
- X
- X /* We should handle "Full-Name:" too, but it doesn't get read by the
- X * news header reader. */
- X (void)CrackFrom(address, fullname, hp->from);
- X#ifdef DO_ADDRESS_CLEANUP
- X Strcpy(address, FixAddress(address));
- X#endif /* DO_ADDRESS_CLEANUP */
- X
- X if (AtCount(address) != 1)
- X p = NULL;
- X else {
- X p = IDX(address, '@');
- X *p++ = '\0';
- X
- X#ifdef DO_ADDRESS_CLEANUP
- X /* If we can find the host's official name use that. */
- X if (host = gethostbyname(p))
- X p = host->h_name;
- X#endif /* DO_ADDRESS_CLEANUP */
- X
- X /* We know have the canonical hostname; glue back together. */
- X Sprintf(scratch, "%s@%s", address, p);
- X Strncpy(address, scratch, sizeof address);
- X address[sizeof address - 1] = '\0';
- X p = IDX(address, '@');
- X *p++ = '\0';
- X }
- X
- X /* Policy decision; what to put in the path? */
- X#ifdef FIXED_PATH
- X Strcpy(hp->path, FIXED_PATH);
- X#else
- X#ifdef GATEWAY
- X Sprintf(scratch, "%s!%s!%s", GATEWAY, p, address);
- X#else
- X Sprintf(scratch, "%s!%s", p, address);
- X#endif /* GATEWAY */
- X Strncpy(hp->path, scratch, sizeof hp->path);
- X hp->path[sizeof hp->path - 1] = '\0';
- X#endif /* FIXED_PATH */
- X
- X /* Restore the @ if we took it out. */
- X if (p)
- X *--p = '@';
- X
- X if (fullname[0]) {
- X p = address + strlen(address);
- X *p++ = ' ';
- X *p++ = '(';
- X p += APPEND(p, fullname);
- X *p++ = ')';
- X *p++ = '\0';
- X }
- X
- X /* Stick the canonicalized From: back in. */
- X Strcpy(hp->from, address);
- X}
- X
- X
- X#define ERROR "\
- XMessage-ID syntax error.\n\
- X*** Please refer to page 23, paragraph 4.6.1. and Appendix D\n\
- X*** of NIC RFC #822 for the correct syntax, and fix your mailer."
- X
- X/*
- X** Check an RFC822 header for validity and hack it to RFC1036 spec.
- X** returns NULL for everything OK, or a character pointer to an
- X** error message.
- X*/
- Xchar *
- XHackHeader(hp, SubjectRequired)
- X register HBUF *hp;
- X int SubjectRequired;
- X{
- X#ifdef REQUIRE_MESSAGE_ID
- X /* Sendmail (almost) always has a Message-ID */
- X if (hp->ident[0] == '\0')
- X return "Message-ID header missing";
- X if (!FixMessageID(hp->ident))
- X return ERROR;
- X#else
- X /* MMDF doesn't always have a Message-ID. */
- X if (hp->ident[0] && !FixMessageID(hp->ident))
- X return ERROR;
- X#endif /* REQUIRE_MESSAGE_ID */
- X
- X /* Newsgroups */
- X if (hp->nbuf[0] == '\0')
- X return "Newsgroups header missing";
- X
- X /* Subject */
- X if (hp->title[0] == '\0') {
- X if (SubjectRequired)
- X return "Subject header missing";
- X Strcpy(hp->title, "(none)");
- X }
- X
- X /* From */
- X if (hp->from[0] == '\0')
- X return "From header missing";
- X FixFrom(hp);
- X
- X /* References and In-Reply-To */
- X if (hp->followid[0])
- X FixReferences(hp);
- X
- X return NULL;
- X}
- X
- X
- X#ifdef TEST
- Xmain()
- X{
- X char buff[256];
- X int i;
- X
- X if (i = isatty(0))
- X (void)printf("Enter addresses:\n");
- X for ( ; ; ) {
- X if (i)
- X (void)printf("> ");
- X if (gets(buff) == NULL || buff[0] == '\0')
- X break;
- X if (buff[0] != '#')
- X (void)printf("\t%s -> %s\n\n", buff, FixAddress(buff));
- X }
- X
- X exit(0);
- X}
- X#endif /* TEST */
- END_OF_FILE
- if test 10652 -ne `wc -c <'hdr.c'`; then
- echo shar: \"'hdr.c'\" unpacked with wrong size!
- fi
- # end of 'hdr.c'
- fi
- if test -f 'lex.l' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lex.l'\"
- else
- echo shar: Extracting \"'lex.l'\" \(3664 characters\)
- sed "s/^X//" >'lex.l' <<'END_OF_FILE'
- X/*
- X** Lexical analyzer for the gag language. We have our own FSA
- X** for comments because it's much smaller and quicker that way.
- X*/
- X%{
- X#include "gate.h"
- X#include "gag.h"
- X
- X/* State of our automaton. */
- Xtypedef enum _STATE {
- X S_STAR, S_NORMAL, S_END
- X} STATE;
- X
- X/* Key-value pair. */
- Xtypedef struct _PAIR {
- X char *name;
- X int value;
- X} PAIR;
- X
- Xchar yyfilename[SM_SIZE];
- Xextern int Errors;
- X
- X/* List of GAG's keywords. */
- XSTATIC PAIR Keywords[] = {
- X { "default", tDEFAULT },
- X { "directory", tDIRECTORY },
- X { "distributions", tDISTRIBUTIONS },
- X { "dotify", tDOTIFY },
- X { "false", tFALSE },
- X { "flags", tFLAGS },
- X { "gateway", tGATEWAY },
- X { "inews", tINEWS },
- X { "mail2news", tMAIL2NEWS },
- X { "mailcontact", tMAILCONTACT },
- X { "mailhost", tMAILHOST },
- X { "mailinglist", tMAILINGLIST },
- X { "mailpost", tMAILPOST },
- X { "moderator", tMODERATOR },
- X { "news2mail", tNEWS2MAIL },
- X { "organization", tORGANIZATION },
- X { "owner", tOWNER },
- X { "request_address", tREQUESTADDR },
- X { "site", tSITE },
- X { "true", tTRUE },
- X { "user", tUSER },
- X { NULL, 0 }
- X};
- X
- X%}
- X
- X%%
- X
- X[-+0-9A-Za-z_.]+ {
- X /* A simple tID or keyword. */
- X register PAIR *p;
- X
- X /* Keyword? */
- X for (p = Keywords; p->name; p++)
- X if (EQ(p->name, yytext))
- X return p->value;
- X yylval.String = COPY(yytext);
- X return tID;
- X }
- X
- X^#[ \t]+[0-9]+[ \t]+"[^\n]+"[^\n]*$ {
- X /* C pre-processor control line. */
- X register char *p;
- X char *namep;
- X
- X /* Find the line number. */
- X for (p = yytext; *p && !isdigit(*p); p++)
- X ;
- X /* Parse the number, find the start of the filename. */
- X for (yylineno = atoi(p); *p && *p != '"'; p++)
- X ;
- X /* March down to the end of the filename. */
- X for (namep = p; *++p && *p != '"'; p++)
- X ;
- X *p = '\0';
- X (void)strncpy(yyfilename, namep, sizeof yyfilename - 1);
- X yyfilename[sizeof yyfilename - 1] = '\0';
- X }
- X
- X\"[^"]* {
- X /* Quoted string. */
- X int c;
- X
- X /* See the Lex paper in Volume 2A or PS1:16
- X * for details on this code. */
- X if (yytext[yyleng - 1] == '\\')
- X yymore();
- X else {
- X if ((c = input()) == '"') {
- X yylval.String = COPY(&yytext[1]);
- X return tID;
- X }
- X unput(c);
- X yyerror("Bad string");
- X }
- X }
- X
- X"/*" {
- X /* Comment. */
- X register STATE S;
- X
- X for (S = S_NORMAL; S != S_END; )
- X switch (input()) {
- X case '/':
- X if (S == S_STAR) {
- X S = S_END;
- X break;
- X }
- X /* FALLTHROUGH */
- X default:
- X S = S_NORMAL;
- X break;
- X case '\0':
- X S = S_END;
- X break;
- X case '*':
- X S = S_STAR;
- X break;
- X }
- X }
- X
- X[ \t\n] {
- X /* Tasty whitespace. */
- X#ifdef lint
- X /* I am compulsive about lint natterings. */
- X yytext[0] = yyinput();
- X yyoutput(yytext[0]);
- X yyunput(yytext[0]);
- X REJECT;
- X#endif /* lint */
- X }
- X
- X. {
- X /* Random special character. */
- X return *yytext;
- X }
- X
- X%%
- X
- X
- X/*
- X** Called by lex at end-of-stream. Return one if no more input.
- X*/
- Xint
- Xyywrap()
- X{
- X return 1;
- X}
- X
- X
- Xyyopen(p)
- X char *p;
- X{
- X if (p == NULL)
- X (void)strcpy(yyfilename, "stdin");
- X else {
- X if ((yyin = fopen(p, "r")) == NULL) {
- X Fprintf(stderr, "%s: Can't open \"%s\" for input, %s.\n",
- X Pname, p, strerror(errno));
- X exit(1);
- X }
- X (void)strcpy(yyfilename, p);
- X }
- X}
- X
- X
- X/*
- X** Write an error message.
- X*/
- Xyyerror(p)
- X char *p;
- X{
- X char buff[SM_SIZE];
- X
- X (void)strncpy(buff, yytext, sizeof buff);
- X buff[sizeof buff - 1] = '\0';
- X Fprintf(stderr, "\"%s\", line %d: %s (near \"%s\")\n",
- X yyfilename, yylineno, p, buff);
- X Errors++;
- X}
- END_OF_FILE
- if test 3664 -ne `wc -c <'lex.l'`; then
- echo shar: \"'lex.l'\" unpacked with wrong size!
- fi
- # end of 'lex.l'
- fi
- if test -f 'mail-interface' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mail-interface'\"
- else
- echo shar: Extracting \"'mail-interface'\" \(2823 characters\)
- sed "s/^X//" >'mail-interface' <<'END_OF_FILE'
- X#! /bin/sh
- X## A portable mail interface program. Original by Piete Brooks,
- X## modified by Rich $alz <rsalz@bbn.com>
- X
- Xmailer="${mailer-/usr/lib/sendmail}"
- Xheaders=false
- X
- X## Decode the arguments.
- Xwhile test $# -gt 0 ; do
- X arg="$1"
- X shift
- X case "$arg" in
- X -A|-ASIS)
- X asis=true
- X ;;
- X -b|-body)
- X body="$body
- X$1"
- X shift
- X ;;
- X -c|-cc)
- X cc="$cc, $1"
- X shift
- X headers=true
- X ;;
- X -f|-from)
- X from="$1"
- X shift
- X headers=true
- X ;;
- X -h|-help)
- X cat <<EOF
- XUsage: $0 [flags] [recipients...]
- X -A -ASIS Send text ASIS, i.e. headers are present in the input
- X -b -body String which is to be the body of the message
- X -c -cc Carbon Copy recipients
- X -f -from From field
- X -h -help This message
- X -r -recip Recipient (passed on command line)
- X -s -subject Set the subject field
- X -t -to Main recipients
- X -* ERROR
- X * treat as recipients
- XEOF
- X exit 1
- X ;;
- X -r|-recip)
- X recip="$recip $1"
- X shift
- X ;;
- X -s|-subject)
- X subject="$subject, $1"
- X shift
- X headers=true
- X ;;
- X -t|-to)
- X to="$to, $1"
- X shift
- X headers=true
- X ;;
- X -*)
- X echo $0: invalid argument \""$arg"\"
- X exit 1
- X ;;
- X *)
- X to="$to, $arg"
- X ;;
- X esac
- Xdone
- X
- X## If no recipients, send to postmaster.
- Xcase "$to$cc$recip" in
- X'')
- X recip=postmaster
- X ;;
- Xesac
- X
- X## If we got no headers on the command line, read them from the message.
- Xcase $headers in
- Xfalse)
- X asis=true
- X ;;
- Xesac
- X
- X## Strip off the spurious leading ", " in repeatable items
- Xcase "$to" in
- X', '*)
- X to=`expr "$to" : ", \(.*\)`
- X ;;
- Xesac
- Xcase "$cc" in
- X', '*)
- X cc=`expr "$cc" : ", \(.*\)`
- X ;;
- Xesac
- Xcase "$subject" in ', '*)
- X subject=`expr "$subject" : ", \(.*\)`
- X ;;
- Xesac
- X
- X## Now do the business.
- Xcase "$mailer" in
- X*/sendmail|sendmail|*/sendmail' '*|sendmail' '*)
- X args="-oi"
- X if [ -z "$recip" ] ; then
- X args="$args -t"
- X fi
- X (
- X if [ ! -z "$subject" ] ; then
- X echo "Subject: $subject"
- X fi
- X if [ ! -z "$from" ] ; then
- X echo "From: $from"
- X fi
- X if [ ! -z "$to" ] ; then
- X echo "To: $to"
- X fi
- X if [ ! -z "$cc" ] ; then
- X echo "Cc: $cc"
- X fi
- X if [ -z "$asis" ] ; then
- X echo ""
- X fi
- X if [ -z "$body" ] ; then
- X cat
- X else
- X echo "$body" | sed 1d
- X fi
- X ) | $debug $mailer $args $recip
- X ;;
- X
- X*/submit|submit|*/submit' '*|submit' '*)
- X args="-tsz"
- X case "$recip" in
- X if [ -z "$recip" ] ; then
- X if [ ! -z "$to" ] ; then
- X args="${args}gto*"
- X fi
- X if [ ! -z "$cc" ] ; then
- X args="${args}gcc*"
- X fi
- X fi
- X (
- X if [ ! -z "$subject" ] ; then
- X echo "Subject: $subject"
- X fi
- X if [ ! -z "$from" ] ; then
- X echo "From: $from"
- X fi
- X if [ ! -z "$to" ] ; then
- X echo "To: $to"
- X fi
- X if [ ! -z "$cc" ] ; then
- X echo "Cc: $cc"
- X fi
- X if [ -z "$asis" ] ; then
- X echo ""
- X fi
- X if [ -z "$body" ] ; then
- X cat
- X else
- X echo "$body" | sed 1d
- X fi
- X ) | $debug $mailer $args $recip
- X ;;
- X
- X*)
- X echo Unknown mailer 1>&2
- X exit 1
- X ;;
- X
- Xesac
- END_OF_FILE
- if test 2823 -ne `wc -c <'mail-interface'`; then
- echo shar: \"'mail-interface'\" unpacked with wrong size!
- fi
- # end of 'mail-interface'
- fi
- if test -f 'mail2news.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mail2news.1'\"
- else
- echo shar: Extracting \"'mail2news.1'\" \(5516 characters\)
- sed "s/^X//" >'mail2news.1' <<'END_OF_FILE'
- X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/mail2news.1,v 1.11 91/02/12 14:46:17 rsalz Exp $
- X.TH MAIL2NEWS 1 LOCAL
- X.SH NAME
- Xmail2news \- feed a mail message into Usenet news
- X.SH SYNOPSIS
- X.B mail2news
- X[
- X.B \-\&.
- X] [
- X.B \-F
- X] [
- X.BI \-= program
- X] [
- X.BI \-n newsgroups
- X] [
- X.BI \-o organization
- X] [
- X.B inewsflags
- X]
- X.SH DESCRIPTION
- X.I Mail2news
- Xreads an RFC822 Mail message on standard input, writes the headers to conform
- Xwith RFC1036 (superceeding RFC850) Usenet News article.
- XA subject is required, unless one of the
- X.IR inews (8)
- X``\-x'' or ``\-o'' flags are specified
- X(these flags are recognized by
- X.I mail2news
- Xbefore being passed on to
- X.IR inews ).
- X.PP
- XIf the ``\-.'' flag is specified, the modified article is sent to the
- Xstandard output, rather than feed into
- X.IR inews .
- X.PP
- XBy default,
- X.I mail2news
- Xsends its input to ``inews \-h''; this can be changed by using the ``\-=''
- Xflag, which will send the output to the specified program.
- XNote that no argument parsing is done, so that only a single word may
- Xbe specified with the ``\-='' flag.
- X.PP
- XThe options used by
- X.I mail2news
- Xare typically punctuation characters, to avoid conflicts with any letters
- Xthat might be used by
- X.I inews
- Xor any other news-processing program.
- X.PP
- XAs a concession to
- X.IR sendmail (8)
- Xalias processing the argument to the ``\-o'' flag is handled specially.
- XSince many
- X.I sendmail.cf
- Xfiles do not have the ``preserve case'' flag on for the ``prog'' mailer,
- Xa period in the argument means that the following character should be converted
- Xto uppercase; two periods mean to output a single period.
- XFor example, if the following line is in
- X.IR /usr/lib/aliases (5):
- X.RS
- Xpost\-news\-admin:
- X "|/usr/local/bin/mail2news \-o '.the .b...b...n.. .gateway' \-n news.admin"
- X.RE
- Xthen messages to mailed to
- X.I post\-news\-admin
- Xwill be posted to the ``news.admin'' newsgroup with the following header line:
- X.RS
- XOrganization: The B.B.N. Gateway
- X.RE
- X.PP
- XIf the ``\-F'' flag is given, then
- X.I mail2news
- Xwill try to filter out
- Xthe ``please add me to your mailing list'' messages often sent by
- Xnetwork neophytes.
- XThis is done by looking for short messages which have words like
- X.I subscribe
- Xin them.
- X.PP
- X.I Mail2news
- Xcan modify the newsgroups an article is sent to, based on regular expressions
- Xfound in the ``Title:'', ``Keywords:'', and ``Summary:'' headers.
- XThe headers are scanned once for each newsgroup the article is originally
- Xdestined for, provided a mapping file exists for the newsgroup.
- X(The path to the mapping file depends on a compile\-time parameter.)
- XFor example, if a mail message is to be sent to
- X.I talk.foo
- Xand
- X.IR soc.bar ,
- X.I mail2news
- Xwill scan the headers twice.
- XIf the file
- X.I /usr/lib/news/.admin/talk.foo
- X(or
- X.IR /usr/spool/news/talk/foo/recnews.cmd )
- Xexists, the commands in that file are interpreted.
- XThe scan is repeated, with the appropriate file for
- X.IR soc.bar .
- XIn the explanation below, the ``current newsgroup'' will be first
- X.I talk.foo
- Xand then
- X.IR soc.bar .
- X.PP
- XBlank lines, and lines beginning with a pound sign
- X.RI ( # )
- Xare ignored.
- XOther lines should like like this:
- X.RS
- X.IR "delim pattern delim command whitespace " "[" "arg" "]"
- X.RE
- XThe
- X.I delim
- Xcan be any character; if it appears in the pattern, it should be
- Xpreceeded by a backslash
- X.RI ( \e ).
- XThe
- X.I pattern
- Xis an
- X.RI `` ed (1)\-style''
- Xregular expression, as detailed in the
- X.IR regex (3L)
- Xmanual page.
- XThe
- X.I command
- Xis a single letter from the set
- X.RI [ adkmq ],
- Xand is described below.
- XThe
- X.I whitespace
- Xis, obviously, any combination of spaces and tabs.
- XFinally, the optional
- X.I arg
- Xshould be a comma\-separated list of newsgroups to be acted on by the
- Xcommand.
- X.PP
- XThe valid commands are:
- X.RS
- X.nf
- X.ta \w'm 'u +\w'Quiet kill 'u
- Xa Add All newsgroups in the arg are added
- Xd Delete The current group is deleted from the article
- Xk Kill The article is returned, and arg is given as a contact name
- Xm Move The current group is deleted and the arg group is added
- Xq Quiet kill The article is quietly ignored
- X.fi
- X.RE
- X.PP
- XFor example, here is a fragment from the mapping file for a
- X.I local.bboard
- Xnewsgroup:
- X.RS
- X.nf
- X.ta \w'/apartment/m 'u
- X# Move seminars and talks
- X/seminar/m local.seminars,region.seminars
- X/lecture/m local.seminars,region.seminars
- X# Move housing requests
- X/housing/m local.housing
- X/apartment/m local.housing
- X# Kill flames
- X/flame/k the anti-flame society
- X/jerk/q @placeholder
- X# Copy machine downtime announcements
- X/downtime/a local.config,news.config
- X# If you want something, it's not forsale
- X/want/a local.wanted
- X/want/d @placeholder
- X.fi
- X.RE
- XThe last two lines show how one might tweak cross\-posts, if the mapping
- Xfile were for a
- X.I local.wanted
- Xnewsgroup.
- X.SH DIAGNOSTICS
- XAlmost all return values from system calls and standard I/O library routines
- Xare checked.
- XIf anything goes wrong, a diagnostic message is sent to standard error, where
- Xit will presumably be picked up by
- X.I sendmail
- X(or other mail-processing program) and returned to the originator, who will
- Xin turn be confused because she doesn't know anything at all about this
- Xgateway program.
- X.SH FILES
- X.ta \w'uucp\-2\-inet 'u
- Xuucp\-2\-inet Mapping of ``Path:'' names to Internet hostnames.
- X.br
- Xinews News delivery program.
- X.br
- XThe full paths to these files are compile\-time constants; see
- X.I gate.h
- Xin the source for the exact details.
- X.SH "SEE ALSO"
- Xgag(1L), mkmailpost(1L), news2mail(1L).
- X.SH AUTHORS
- XRich $alz <rsalz@bbn.com>, after
- X.I nrecnews
- Xby
- X.br
- XErik E. Fair <fair@apple.com>.
- X.br
- XOzan Yigit <yunexus!oz> wrote the regular\-expression routines.
- END_OF_FILE
- if test 5516 -ne `wc -c <'mail2news.1'`; then
- echo shar: \"'mail2news.1'\" unpacked with wrong size!
- fi
- # end of 'mail2news.1'
- fi
- if test -f 'misc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'misc.c'\"
- else
- echo shar: Extracting \"'misc.c'\" \(2955 characters\)
- sed "s/^X//" >'misc.c' <<'END_OF_FILE'
- X/*
- X** Miscellaneous routines.
- X*/
- X#include "gate.h"
- X#ifdef RCSID
- Xstatic char RCS[] =
- X "$Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/misc.c,v 1.7 91/02/12 14:47:53 rsalz Exp $";
- X#endif /* RCSID */
- X
- X
- X/*
- X** Allocate memory.
- X*/
- Xalign_t
- XMyAlloc(i)
- X int i;
- X{
- X align_t p;
- X
- X if ((p = (align_t)malloc((unsigned int)i)) == NULL) {
- X Fprintf(stderr, "%s: Could not allocate %d bytes: %s\n",
- X Pname, i, strerror(errno));
- X exit(EX_OSERR);
- X }
- X return p;
- X}
- X
- X
- X#ifndef HAVE_STRERROR
- X/*
- X** Return a printable representation of errno.
- X*/
- Xchar *
- Xstrerror(x)
- X int x;
- X{
- X static char buff[20];
- X
- X if (x >= 0 && x < sys_nerr)
- X return sys_errlist[x];
- X Sprintf(buff, "Error code %d", x);
- X return buff;
- X}
- X#endif /* HAVE_STRERROR */
- X
- X
- X/*
- X** Free up something that Split() made.
- X*/
- Xvoid
- XSplitFree(p)
- X char ***p;
- X{
- X if (p && *p) {
- X free((*p)[0]);
- X free((char *)*p);
- X *p = NULL;
- X }
- X}
- X
- X
- X/*
- X** This is an AWK-style split routine. If the split character is NULL,
- X** we split on space or tab and eat long stretches of same (that is, no
- X** null fields will result). Returns number of fields made.
- X*/
- Xint
- XSplit(s, p, c)
- X register char *s;
- X char ***p;
- X register char c;
- X{
- X register char *cp;
- X register int blank;
- X register int n;
- X register int i;
- X
- X if (s == NULL || *s == '\0') {
- X Fprintf(stderr, "%s: Someone was a pinhead!\n", Pname);
- X abort();
- X }
- X
- X i = strlen(s) + 1;
- X cp = NEW(char, i);
- X /* This is too much -- we'll realloc what we really need later. */
- X *p = NEW(char*, i);
- X
- X if (c == '\0') {
- X /* Eat multiple whitespace characters. */
- X for (blank = TRUE, n = 0; *s; s++)
- X if (WHITE(*s)) {
- X if (!blank)
- X *cp++ = '\0';
- X blank = TRUE;
- X }
- X else {
- X if (blank)
- X (*p)[n++] = cp;
- X *cp++ = *s;
- X blank = FALSE;
- X }
- X
- X if (n == 0) {
- X (*p)[0] = cp;
- X SplitFree(p);
- X return 0;
- X }
- X }
- X else
- X /* Normal case: find all occurrences of "c" and null them as field
- X * terminators; add new string starts to the array of pointers to
- X * strings. */
- X for ((*p)[0] = cp, n = 1; *s; s++)
- X if (*s == c) {
- X *cp++ = '\0';
- X (*p)[n++] = cp;
- X }
- X else
- X *cp++ = *s;
- X
- X /* Free up the excess space. */
- X *p = (char **)REALLOC(*p, (n + 1) * sizeof (char *));
- X (*p)[n] = NULL;
- X return n;
- X}
- X
- X
- X
- X/*
- X** Read in a file of lines, dump it into an array of strings.
- X*/
- Xchar **
- XReadFile(Name)
- X char *Name;
- X{
- X register FILE *F;
- X register char **v;
- X register char *p;
- X register int i;
- X char **value;
- X char buff[SM_SIZE];
- X
- X /* Open file, count number of lines therein. */
- X if ((F = fopen(Name, "r")) == NULL) {
- X perror(Name);
- X exit(EX_OSFILE);
- X }
- X for (i = 1; fgets(buff, sizeof buff, F); i++)
- X ;
- X
- X rewind(F);
- X for (v = value = NEW(char*, i); fgets(buff, sizeof buff, F); ) {
- X if (p = IDX(buff, '\n'))
- X *p = '\0';
- X if (buff[0] && buff[0] != '#')
- X *v++ = COPY(buff);
- X }
- X
- X *v = NULL;
- X return value;
- X}
- END_OF_FILE
- if test 2955 -ne `wc -c <'misc.c'`; then
- echo shar: \"'misc.c'\" unpacked with wrong size!
- fi
- # end of 'misc.c'
- fi
- if test -f 'news2mail.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'news2mail.1'\"
- else
- echo shar: Extracting \"'news2mail.1'\" \(5362 characters\)
- sed "s/^X//" >'news2mail.1' <<'END_OF_FILE'
- X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/news2mail.1,v 1.7 91/02/12 14:49:43 rsalz Exp $
- X.TH NEWS2MAIL 1 LOCAL
- X.SH NAME
- Xnews2mail \- feed a Usenet news article to mail
- X.SH SYNOPSIS
- X.B news2mail
- X[
- X.BI \-E var=value
- X] [
- X.B \-.
- X]
- Xlistname listaddr listadmin host [ article ]
- X.SH DESCRIPTION
- X.PP
- X.I News2mail
- Xreads a news article edits the headers to make it look like an RFC822 mail
- Xmessage.
- XIt feeds the results to
- Xand feeds it to
- X.IR sendmail (8),
- X.IR MMDF (8),
- Xor a shell script.
- XIf the ``\-.'' flag is used, then the results are sent to standard output,
- Xfor debugging.
- X.PP
- XThe article is taken from the file specified on the command line, or read
- Xfrom standard input if not specified.
- X.PP
- XThe ``\-E'' flag can be used to set environment variables for the delivery
- Xprogram that is invoked.
- XThey should be of the form ``name=value'' as in
- X\&``\-E mailer=/usr/lib/pp/cmds/submit''.
- X.PP
- X.I News2mail
- Xswallows control messages,
- Xremoves all but the last three entries from the ``References'' header,
- Xand merges the ``From'' and ``Path'' headers to build a single
- X``From'' header for the mail message (see below).
- XThe ``Date,'' ``Subject,'' ``Reply\-To,'' ``Message\-ID,'' and ``Organization''
- Xheaders are passed through unchanged.
- XAny other headers in the original input are removed.
- X.PP
- XTo ``To,'' and ``Sender'' headers and the SMTP destination envelope are set
- Xaccording to the parameters specified on the command line.
- XThe ``To'' header is set to be \fIlistname\fP, with \fI@host\fP appended if there
- Xis no atsign in \fIlistname\fP.
- XThis should contain the name of the mailing list.
- XThe mail is actually sent to \fIlistaddr\fP by specifying it as the
- Xrecipient in the mailer command line.
- X(If \fIlistaddr\fP does not have an atsign, then \fIlistaddr@host\fP is used.)
- XBy treating the ``To'' header and the destination envelope separately,
- Xother members of the mailing list can properly reply to the messages that
- Xpass through
- X.IR news2mail .
- XIn addition, \fIlistaddr\fP can be an address that sends to everyone on
- Xthe list except the gateway.
- XThis is an optimization, however, because
- X.IR inews (8)
- Xwill reject any Message-ID that it has already seen.
- X.PP
- XThe ``Sender'' header is set to be \fIlistadmin\fP, with \fI@host\fP
- Xappended if there is no atsign in \fIlistadmin\fP.
- XThese values should correspond to the maintainer of the mailing list.
- XSome mailers will also automatically fill in the ``Return-Path'' header
- Xwith this value.
- X.PP
- XThe goal of the header manipulations is to send the news article to all
- Xrecipient of the mailing list, but with the headers set so that delivery
- Xerrors are sent to the list maintainer for disposition.
- X.PP
- X.IR Mail2news
- Xtries to shrink the ``Path'' header by taking note of neighboring
- X\s-2UUCP\s0 hosts and scanning for other Internet hosts that it can
- Xshort\-circuit to.
- X.IR Uuname (1)
- Xis used to check for \s-2UUCP\s0 neighbors; the file
- X.I uucp\-2\-inet
- Xis read to map \s-2UUCP\s0 names to Internet domain names.
- XFor efficiency,
- X.I mail2news
- Xstores
- X.IR uuname 's
- Xoutput in a private file, and will only call
- X.I uuname
- Xif the file is older than the \s-2UUCP\s0
- X.IR L.sys (5)
- Xfile.
- X.PP
- XIn order to have
- X.I sendmail
- Xbelieve that the headers it has created are valid,
- X.I news2mail
- Xmust be able to
- X.IR setuid (2)
- Xto one of
- X.IR sendmail 's
- Xtrusted users.
- X.SH EXAMPLE
- X.PP
- XSuppose the following article arrives
- X.IR comp.sources.unix\| :
- X.RS
- X.nf
- XPath: bbn!husc6!uunet!rsalz
- XFrom: rsalz@uunet.UU.NET (Rich Salz)
- XNewsgroups: comp.sources.unix
- XSubject: v10INF1: Introduction to comp.sources.unix
- XMessage\-ID: <830@uunet.UU.NET>
- XDate: 10 Aug 87 21:57:17 GMT
- XExpires: 10 Nov 87 22:17:17 GMT
- XOrganization: UUNET Communications Services, Arlington, VA
- XLines: 189
- XApproved: rsalz@uunet.UU.NET
- X
- XThis is the first of two introductory articles about comp.sources.unix.
- X\&...
- X.fi
- X.RE
- XAlso, assume the following line is in your news sys file (see
- X.IR news (5)):
- X.RS
- X.nf
- Xgateway:world,comp.sources.unix::\e
- X.ti +.5i
- Xnews2mail unix\-sources rsalz unix\-sources\-request bbn.com
- X.fi
- X.RE
- XThe
- X.I news2mail
- Xprogram would generate the following article and feed it to
- X.IR sendmail :
- X.RS
- X.nf
- XReceived: from USENET by bbn.com with netnews
- X for rsalz@bbn.com (unix\-sources@bbn.com);
- X contact usenet@bbn.com if you have questions.
- XTo: unix\-sources@bbn.com
- XDate: 10 Aug 87 21:57:17 GMT
- XFrom: rsalz@uunet.uu.net (Rich Salz)
- XSender: unix\-sources\-request@bbn.com
- XSubject: v10INF1: Introduction to comp.sources.unix
- XMessage\-ID: <830@uunet.UU.NET>
- XOrganization: UUNET Communications Services, Arlington, VA
- X
- XThis is the first of two introductory articles about comp.sources.unix.
- X\&...
- X.fi
- X.RE
- X.SH DIAGNOSTICS
- XMost return values from I/O routines are checked; if anything goes
- Xwrong, a diagnostic message is sent to a log file.
- XThis file will occasionally have to be examined and trimmed.
- X.SH FILES
- X.ta \w'news2mail.out 'u
- Xnews2mail.out Error log (standard error)
- X.br
- Xuucp\-2\-inet Mapping of ``Path'' names to Internet hostnames.
- X.br
- Xuuname.out Last output from
- X.IR uuname .
- X.br
- XThe full paths to these files are compile\-time constants; see
- X.I gate.h
- Xin the source for the exact details.
- X.SH "SEE ALSO"
- Xgag(1L), mail2news(1L).
- X.SH AUTHOR
- XRich $alz <rsalz@bbn.com>, after a set of scripts and a excellent manpage by
- X.br
- XErik E. Fair <fair@apple.com>.
- X.br
- XPiete Brooks <pb@computer-lab.cambridge.ac.uk> helped write the option-handling.
- END_OF_FILE
- if test 5362 -ne `wc -c <'news2mail.1'`; then
- echo shar: \"'news2mail.1'\" unpacked with wrong size!
- fi
- # end of 'news2mail.1'
- fi
- if test -f 'signoff.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'signoff.c'\"
- else
- echo shar: Extracting \"'signoff.c'\" \(3327 characters\)
- sed "s/^X//" >'signoff.c' <<'END_OF_FILE'
- X/*
- X** SIGNOFF
- X** Quickie hack to see of a mail message is a "please drop me" request.
- X** Exit's with status 0 if it is a regular message, or 1 if it appears to
- X** be a one of this administrative requests that annoy everyone when
- X** they're sent to the whole list. Optional first argument is the name
- X** of the input file, or stdin is read if none is given.
- X**
- X** Original program written by Russ Nelson, <nelson@clutx.clarkson.edu>.
- X** Severely hacked on by Rich $alz, <rsalz@bbn.com>. This program is
- X** basically incorporated into mail2news; it's pulled out here for
- X** demonstration.
- X**
- X** For example, here is a script that could be used as a wrapper around
- X** the mail2news program:
- X** #! /bin/sh
- X** cat >/tmp/signoff$$
- X** if /usr/lib/news/signoff </tmp/signoff$$ ; then
- X** /usr/ucb/Mail -s "Sign on/off request" usenet </tmp/signoff$$
- X** else
- X** /usr/lib/news/mail2news.real </tmp/signoff$$
- X** fi
- X** exec rm /tmp/signoff$$
- X**
- X** Russ ran the following test for a month and got only one real message
- X** (a gnu.gcc bug report) treated as a subscription request. He doesn't
- X** know how many subs made it out to the net, tho: that would entail
- X** reading ALL netnews articles -- yuck!
- X**
- X** Put the following line in your news sys file:
- X** allmail:all::/usr/lib/news/ts
- X** here is the "ts" script:
- X** #! /bin/sh
- X** cat >/tmp/ts.$$
- X** /usr/lib/news/signoff </tmp/ts.$$ || mail usenet </tmp/ts.$$
- X** exec rm /tmp/ts.$$
- X**
- X** Perhaps a better way to test is to make the test less conservative,
- X** and see what "real" articles get caught, and make adjustments then?
- X** Comments solicited.
- X*/
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#define EQ(a, b) (strcmp((a), (b)) == 0)
- X
- X
- Xmain(ac, av)
- X int ac;
- X char *av[];
- X{
- X register FILE *F;
- X register char *p;
- X register int c;
- X register int drop_or_add;
- X register int from_or_to;
- X register int mail_word;
- X register int count;
- X char word[128];
- X
- X /* Get input. */
- X if (ac < 2)
- X F = stdin;
- X else if ((F = fopen(av[1], "r")) == NULL) {
- X (void)fprintf(stderr, "%s: cannot open %s\n", av[0], av[1]);
- X exit(1);
- X }
- X
- X /* Skip headers by waiting for the first blank line. */
- X while (fgets(word, sizeof word, F) && *word != '\n')
- X ;
- X
- X /* Clear counts. */
- X drop_or_add = 0;
- X from_or_to = 0;
- X mail_word = 0;
- X count = 0;
- X
- X /* Read input a word at a time. */
- X for (p = word; (c = getc(F)) != EOF; ) {
- X if (!isalpha(c)) {
- X *p = '\0';
- X if (p > word)
- X count++;
- X p = word;
- X
- X if (EQ(word, "remove") || EQ(word, "drop") || EQ(word, "off")
- X || EQ(word, "subscribe") || EQ(word, "get") || EQ(word, "add"))
- X drop_or_add++;
- X else if (EQ(word, "from") || EQ(word, "to"))
- X from_or_to++;
- X else if (EQ(word, "mail") || EQ(word, "mailing")
- X || EQ(word, "list") || EQ(word, "dl"))
- X mail_word++;
- X }
- X else if (p < &word[sizeof word - 1])
- X *p++ = isupper(c) ? tolower(c) : c;
- X }
- X
- X (void)fclose(F);
- X
- X /* Use fancy-shmancy AI techniques to determine what the message is. */
- X c = count < 25 && drop_or_add && from_or_to && mail_word;
- X
- X#ifdef DEBUG
- X printf("%s: %d words, %d drop, %d mail --> %s\n",
- X av[1] ? av[1] : "<stdin>",
- X count, drop_or_add, mail_word,
- X c ? "yes" : "no");
- X#endif /* DEBUG */
- X
- X /* Exit appropriately. */
- X exit(c ? 0 : 1);
- X}
- END_OF_FILE
- if test 3327 -ne `wc -c <'signoff.c'`; then
- echo shar: \"'signoff.c'\" unpacked with wrong size!
- fi
- # end of 'signoff.c'
- fi
- if test -f 'sysexits.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sysexits.h'\"
- else
- echo shar: Extracting \"'sysexits.h'\" \(4568 characters\)
- sed "s/^X//" >'sysexits.h' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1987 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Berkeley. The name of the
- X * University may not be used to endorse or promote products derived
- X * from this software without specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * @(#)sysexits.h 4.5 (Berkeley) 7/6/88
- X */
- X
- X/*
- X** SYSEXITS.H -- Exit status codes for system programs.
- X**
- X** This include file attempts to categorize possible error
- X** exit statuses for system programs, notably delivermail
- X** and the Berkeley network.
- X**
- X** Error numbers begin at EX__BASE to reduce the possibility of
- X** clashing with other exit statuses that random programs may
- X** already return. The meaning of the codes is approximately
- X** as follows:
- X**
- X** EX_USAGE -- The command was used incorrectly, e.g., with
- X** the wrong number of arguments, a bad flag, a bad
- X** syntax in a parameter, or whatever.
- X** EX_DATAERR -- The input data was incorrect in some way.
- X** This should only be used for user's data & not
- X** system files.
- X** EX_NOINPUT -- An input file (not a system file) did not
- X** exist or was not readable. This could also include
- X** errors like "No message" to a mailer (if it cared
- X** to catch it).
- X** EX_NOUSER -- The user specified did not exist. This might
- X** be used for mail addresses or remote logins.
- X** EX_NOHOST -- The host specified did not exist. This is used
- X** in mail addresses or network requests.
- X** EX_UNAVAILABLE -- A service is unavailable. This can occur
- X** if a support program or file does not exist. This
- X** can also be used as a catchall message when something
- X** you wanted to do doesn't work, but you don't know
- X** why.
- X** EX_SOFTWARE -- An internal software error has been detected.
- X** This should be limited to non-operating system related
- X** errors as possible.
- X** EX_OSERR -- An operating system error has been detected.
- X** This is intended to be used for such things as "cannot
- X** fork", "cannot create pipe", or the like. It includes
- X** things like getuid returning a user that does not
- X** exist in the passwd file.
- X** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
- X** etc.) does not exist, cannot be opened, or has some
- X** sort of error (e.g., syntax error).
- X** EX_CANTCREAT -- A (user specified) output file cannot be
- X** created.
- X** EX_IOERR -- An error occurred while doing I/O on some file.
- X** EX_TEMPFAIL -- temporary failure, indicating something that
- X** is not really an error. In sendmail, this means
- X** that a mailer (e.g.) could not create a connection,
- X** and the request should be reattempted later.
- X** EX_PROTOCOL -- the remote system returned something that
- X** was "not possible" during a protocol exchange.
- X** EX_NOPERM -- You did not have sufficient permission to
- X** perform the operation. This is not intended for
- X** file system problems, which should use NOINPUT or
- X** CANTCREAT, but rather for higher level permissions.
- X** For example, kre uses this to restrict who students
- X** can send mail to.
- X**
- X** Maintained by Eric Allman (eric@berkeley, ucbvax!eric) --
- X** please mail changes to me.
- X**
- X** @(#)sysexits.h 4.5 7/6/88
- X*/
- X
- X# define EX_OK 0 /* successful termination */
- X
- X# define EX__BASE 64 /* base value for error messages */
- X
- X# define EX_USAGE 64 /* command line usage error */
- X# define EX_DATAERR 65 /* data format error */
- X# define EX_NOINPUT 66 /* cannot open input */
- X# define EX_NOUSER 67 /* addressee unknown */
- X# define EX_NOHOST 68 /* host name unknown */
- X# define EX_UNAVAILABLE 69 /* service unavailable */
- X# define EX_SOFTWARE 70 /* internal software error */
- X# define EX_OSERR 71 /* system error (e.g., can't fork) */
- X# define EX_OSFILE 72 /* critical OS file missing */
- X# define EX_CANTCREAT 73 /* can't create (user) output file */
- X# define EX_IOERR 74 /* input/output error */
- X# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
- X# define EX_PROTOCOL 76 /* remote error in protocol */
- X# define EX_NOPERM 77 /* permission denied */
- X# define EX_CONFIG 78 /* configuration error */
- END_OF_FILE
- if test 4568 -ne `wc -c <'sysexits.h'`; then
- echo shar: \"'sysexits.h'\" unpacked with wrong size!
- fi
- # end of 'sysexits.h'
- fi
- if test -f 'uucp-2-inet' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'uucp-2-inet'\"
- else
- echo shar: Extracting \"'uucp-2-inet'\" \(3301 characters\)
- sed "s/^X//" >'uucp-2-inet' <<'END_OF_FILE'
- X## This file maps UUCP names to Internet names.
- X## Blank lines, and lines starting with # are ignored.
- X## $Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/uucp-2-inet,v 1.2 87/10/01 14:06:50 rsalz Release1 $
- X## (I added uunet and bbn.)
- Xames ames.arpa
- Xaurora ames-aurora.arpa
- Xkestrel kestrel.arpa
- Xlll-crg lll-crg.arpa
- Xlll-lcc lll-lcc.arpa
- Xstyx lll-tis-b.arpa
- Xcmcl2 nyu.arpa
- Xyale yale.arpa
- Xrandvax rand-unix.arpa
- Xosu-eddie ohio-state.arpa
- Xuunet uunet.uu.net
- X
- Xcunyvm.bitnet cunyvm.bitnet
- Xpsuvm.bitnet psuvm.bitnet
- X
- Xmcnc mcnc.org
- X
- Xbrl-smoke smoke.brl.mil
- Xbrl-sem sem.brl.mil
- Xbrl-adm adm.brl.mil
- Xcod cod.nosc.mil
- Xmarlin marlin.nosc.mil
- Xmplvax mplvax.nosc.mil
- Xnoscvax bass.nosc.mil
- X
- Xelroy elroy.jpl.nasa.gov
- Xseismo seismo.css.gov
- Xlanl lanl.gov
- Xmordor mordor.s1.gov
- Xhc hc.dspo.gov
- X
- Xbbn bbn.com
- Xhplabs hplabs.hp.com
- Xdecwrl decwrl.dec.com
- Xbellcore bellcore.bellcore.com
- Xpetrus petrus.bellcore.com
- XDiamond diamond.bbn.com
- Xsun sun.com
- Xsri-spam spam.istc.sri.com
- Xsri-unix unix.sri.com
- Xthink think.com
- Xburdvax burdvax.prc.unisys.com
- Xbigburd bigburd.prc.unisys.com
- Xparcvax parcvax.xerox.com
- X
- Xarizona arizona.edu
- XShasta shasta.stanford.edu
- Xacf2 acf2.nyu.edu
- Xacf3 acf3.nyu.edu
- Xacf4 acf4.nyu.edu
- Xcsd2 csd2.nyu.edu
- Xmit-athena athena.mit.edu
- Xathena.mit.edu athena.mit.edu
- Xbatcomputer tcgould.tn.cornell.edu
- Xbu-cs bu-cs.bu.edu
- Xbucsb.bu.edu bucsb.bu.edu
- Xcaip caip.rutgers.edu
- Xcit-vax csvax.caltech.edu
- Xcit-vlsi vlsi.caltech.edu
- Xcornell cu-arpa.cs.cornell.edu
- Xcvl cvl.umd.edu
- Xendor endor.harvard.edu
- Xeneevax eneevax.umd.edu
- Xernie.Berkeley.EDU ernie.berkeley.edu
- Xglacier glacier.stanford.edu
- Xgvax gvax.cs.cornell.edu
- Xgymble gymble.umd.edu
- Xh.cc.purdue.edu h.cc.purdue.edu
- Xprinceton princeton.edu
- Xharvard harvard.harvard.edu
- Xhusc4 husc4.harvard.edu
- Xhusc6 husc6.harvard.edu
- Xoddjob oddjob.uchicago.edu
- Xgargoyle gargoyle.uchicago.edu
- Xsphinx sphinx.uchicago.edu
- Xim4u im4u.utexas.edu
- Xius2.cs.cmu.edu ius2.cs.cmu.edu
- Xsei.cmu.edu sei.cmu.edu
- Xj.cc.purdue.edu j.cc.purdue.edu
- Xll-xn xn.ll.mit.edu
- Xmimsy mimsy.umd.edu
- Xmit-amt media-lab.media.mit.edu
- Xmit-athena athena.mit.edu
- Xmit-eddie eddie.mit.edu
- Xmit-hermes hermes.ai.mit.edu
- Xmit-prep prep.ai.mit.edu
- Xmit-trillian trillian.mit.edu
- Xprep.ai.mit.edu prep.ai.mit.edu
- Xpt.cs.cmu.edu pt.cs.cmu.edu
- Xpur-ee ee.ecn.purdue.edu
- Xpurdue purdue.edu
- Xriacs icarus.riacs.edu
- Xrice rice.edu
- Xrochester cs.rochester.edu
- Xrover.ri.cmu.edu rover.ri.cmu.edu
- Xrutgers rutgers.rutgers.edu
- Xsdcsvax sdcsvax.ucsd.edu
- Xspice.cs.cmu.edu spice.cs.cmu.edu
- Xsvax svax.cs.cornell.edu
- Xtalcott talcott.harvard.edu
- Xtopaz topaz.rutgers.edu
- Xucbcad cad.berkeley.edu
- Xucbvax ucbvax.berkeley.edu
- Xucla-cs locus.ucla.edu
- Xuiucdcs a.cs.uiuc.edu
- Xuiucdcsb b.cs.uiuc.edu
- Xuiucdcsc c.cs.uiuc.edu
- Xuiucdcsm m.cs.uiuc.edu
- Xuiucdcsp p.cs.uiuc.edu
- Xuiucuxc uxc.cso.uiuc.edu
- Xumcp-cs mimsy.umd.edu
- Xumd5 umd5.umd.edu
- Xoberon usc-oberon.usc.edu
- Xut-ngp ngp.utexas.edu
- Xut-sally sally.utexas.edu
- Xutah-cs cs.utah.edu
- Xutah-gr gr.utah.edu
- Xutastro astro.as.utexas.edu
- Xuw-beaver beaver.cs.washington.edu
- Xuw-june june.cs.washington.edu
- Xuwmacc unix.macc.wisc.edu
- Xuwvax rsch.wisc.edu
- Xwjh12 wjh12.harvard.edu
- X
- XCS.UCL.AC.UK cs.ucl.ac.uk
- Xcs.ucl.ac.uk cs.ucl.ac.uk
- END_OF_FILE
- if test 3301 -ne `wc -c <'uucp-2-inet'`; then
- echo shar: \"'uucp-2-inet'\" unpacked with wrong size!
- fi
- # end of 'uucp-2-inet'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-